Passed
Branch v8.x (3f6847)
by Rafael S.
02:03
created

riff-chunks.js ➔ getSubChunkIndex_   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 2
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
nop 2
1
/*
2
 * riff-chunks: Read and write the chunks of RIFF and RIFX files.
3
 * https://github.com/rochars/riff-chunks
4
 *
5
 * Copyright (c) 2017-2018 Rafael da Silva Rocha.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 */
27
28
/**
29
 * @fileoverview The riff-chunks API.
30
 */
31
32
/** @module riffChunks */
33
34
import {unpackFrom, unpackString} from './byte-data.js';
35
36
/** @private */
37
const uInt32_ = {bits: 32};
38
/** @type {number} */
39
let head_ = 0;
40
41
/**
42
 * Return the chunks in a RIFF/RIFX file.
43
 * @param {!Uint8Array} buffer The file bytes.
44
 * @return {!Object} The RIFF chunks.
45
 */
46
export function riffChunks(buffer) {
47
    head_ = 0;
48
    let chunkId = getChunkId_(buffer, 0);
49
    uInt32_.be = chunkId == 'RIFX';
50
    let format = unpackString(buffer, 8, 4);
51
    head_ += 4;
52
    return {
53
        chunkId: chunkId,
54
        chunkSize: getChunkSize_(buffer, 0),
55
        format: format,
56
        subChunks: getSubChunksIndex_(buffer)
57
    };
58
}
59
60
/**
61
  * Find a chunk by its fourCC_ in a array of RIFF chunks.
62
  * @param {!Object} chunks The wav file chunks.
63
  * @param {string} chunkId The chunk fourCC_.
64
  * @param {boolean} multiple True if there may be multiple chunks
65
  *    with the same chunkId.
66
  * @return {?Array<!Object>}
67
  * @private
68
  */
69
export function findChunk_(chunks, chunkId, multiple=false) {
70
  /** @type {!Array<!Object>} */
71
  let chunk = [];
72
  for (let i=0; i<chunks.length; i++) {
73
    if (chunks[i].chunkId == chunkId) {
74
      if (multiple) {
75
        chunk.push(chunks[i]);
76
      } else {
77
        return chunks[i];
78
      }
79
    }
80
  }
81
  if (chunkId == 'LIST') {
82
    return chunk.length ? chunk : null;
83
  }
84
  return null;
85
}
86
87
/**
88
 * Return the sub chunks of a RIFF file.
89
 * @param {!Uint8Array} buffer the RIFF file bytes.
90
 * @return {!Array<Object>} The subchunks of a RIFF/RIFX or LIST chunk.
91
 * @private
92
 */
93
function getSubChunksIndex_(buffer) {
94
    let chunks = [];
95
    let i = head_;
96
    while(i <= buffer.length - 8) {
97
        chunks.push(getSubChunkIndex_(buffer, i));
98
        i += 8 + chunks[chunks.length - 1].chunkSize;
99
        i = i % 2 ? i + 1 : i;
100
    }
101
    return chunks;
102
}
103
104
/**
105
 * Return a sub chunk from a RIFF file.
106
 * @param {!Uint8Array} buffer the RIFF file bytes.
107
 * @param {number} index The start index of the chunk.
108
 * @return {!Object} A subchunk of a RIFF/RIFX or LIST chunk.
109
 * @private
110
 */
111
function getSubChunkIndex_(buffer, index) {
112
    let chunk = {
113
        chunkId: getChunkId_(buffer, index),
114
        chunkSize: getChunkSize_(buffer, index),
115
    };
116
    if (chunk.chunkId == 'LIST') {
117
        chunk.format = unpackString(buffer, index + 8, 4);
118
        head_ += 4;
119
        chunk.subChunks = getSubChunksIndex_(buffer);
120
    } else {
121
        let realChunkSize = chunk.chunkSize % 2 ?
122
            chunk.chunkSize + 1 : chunk.chunkSize;
123
        head_ = index + 8 + realChunkSize;
124
        chunk.chunkData = {
125
            start: index + 8,
126
            end: head_
127
        };
128
    }
129
    return chunk;
130
}
131
132
/**
133
 * Return the fourCC_ of a chunk.
134
 * @param {!Uint8Array} buffer the RIFF file bytes.
135
 * @param {number} index The start index of the chunk.
136
 * @return {string} The id of the chunk.
137
 * @private
138
 */
139
function getChunkId_(buffer, index) {
140
    head_ += 4;
141
    return unpackString(buffer, index, 4);
142
}
143
144
/**
145
 * Return the size of a chunk.
146
 * @param {!Uint8Array} buffer the RIFF file bytes.
147
 * @param {number} index The start index of the chunk.
148
 * @return {number} The size of the chunk without the id and size fields.
149
 * @private
150
 */
151
function getChunkSize_(buffer, index) {
152
    head_ += 4;
153
    return unpackFrom(buffer, uInt32_, index + 4);
154
}
155